package cn.yaoguangl.autotransmissioncontrol;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.ScrollView;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleIndicateCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleScanCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.leonxtp.library.YModem;
import com.leonxtp.library.YModemListener;

import java.io.UnsupportedEncodingException;
import java.util.List;

public class MainActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener, View.OnClickListener {


    private TextView mStatusTextView;
    private Switch mSwitch1;
    private Switch mSwitch2;
    private Switch mSwitch3;
    private Switch mSwitch4;
    private Switch mSwitch5;
    private Switch mSwitch6;
    private Switch mSwitch7;
    private Switch mLogSwitch;
    private TextView mBalance1TextView;
    private TextView mBalance2TextView;
    private TextView mMsgTextView;
    private TextView mBootStatusTextView;
    private TextView mProcessTextView;
    private ScrollView mMsgScrollView;
    private EditText mSendEditText;
    private Button mSendButton;
    private Button mUpdateButton;
    private Button mGoAppButton;
    private Button mGoDownLoadButton;
    private Button mRebootChipButton;
    Button mBalance1ZeroBt;
    Button mBalance1CalBt;
    Button mBalance2ZeroBt;
    Button mBalance2CalBt;

    EditText mCal1EditText;
    EditText mCal2EditText;
    public static BluetoothGattCharacteristic mBluetoothGattCharacteristic;
    public static BluetoothGattService mBluetoothGattService;
    public static BleDevice mBluetoothDevice;
    StringBuilder mMsgStringBuilder = new StringBuilder("");
    StringBuilder mAvailableStringBuilder = new StringBuilder("");
    private boolean mLogOpen = true;
    public static String HEART_RATE_MEASUREMENT = "0000ffe1-0000-1000-8000-00805f9b34fb";
    private YModem mYModem;
    private boolean mStartUpdated = false;
    private long mStartDownLoadTime = 0;
    private long mFinishDownLoadTime = 0;
    private BluetoothListenerReceiver mBtReceiver;

    private static final int MAX_HEIGHT = 99990;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mStatusTextView = findViewById(R.id.bluetooth_status);
        mSwitch1 = findViewById(R.id.sw1);
        mSwitch2 = findViewById(R.id.sw2);
        mSwitch3 = findViewById(R.id.sw3);
        mSwitch4 = findViewById(R.id.sw4);
        mSwitch5 = findViewById(R.id.sw5);
        mSwitch6 = findViewById(R.id.sw6);
        mSwitch7 = findViewById(R.id.sw7);
        mLogSwitch = findViewById(R.id.log_switch);
        mLogSwitch.setChecked(true);
        mBalance1TextView = findViewById(R.id.balance1_val_tv);
        mBalance2TextView = findViewById(R.id.balance2_val_tv);
        mMsgTextView = findViewById(R.id.msg_tv);
        mProcessTextView = (findViewById(R.id.progress_tv));
        mMsgScrollView = findViewById(R.id.msg_sv);
        //mSendEditText = findViewById(R.id.send_et);
        //mSendButton = findViewById(R.id.send_bt);
        mUpdateButton = findViewById(R.id.update_bt);
        mBalance1ZeroBt = findViewById(R.id.balance1_zero_bt);
        mBalance1CalBt = findViewById(R.id.balance1_cal_bt);
        mBalance2ZeroBt = findViewById(R.id.balance2_zero_bt);
        mBalance2CalBt = findViewById(R.id.balance2_cal_bt);
        mGoAppButton = findViewById(R.id.goapp_bt);
        mGoDownLoadButton = findViewById(R.id.godownload_bt);
        mBootStatusTextView = findViewById(R.id.boot_stat_tv);
        mRebootChipButton = findViewById(R.id.reboot_chip_bt);
        mCal1EditText = findViewById(R.id.et_cal1);
        mCal2EditText = findViewById(R.id.et_cal2);

        mBalance1ZeroBt.setOnClickListener(this);
        mBalance1CalBt.setOnClickListener(this);
        mBalance2ZeroBt.setOnClickListener(this);
        mBalance2CalBt.setOnClickListener(this);
        mSwitch1.setOnCheckedChangeListener(this);
        mSwitch2.setOnCheckedChangeListener(this);
        mSwitch3.setOnCheckedChangeListener(this);
        mSwitch4.setOnCheckedChangeListener(this);
        mSwitch5.setOnCheckedChangeListener(this);
        mSwitch6.setOnCheckedChangeListener(this);
        mSwitch7.setOnCheckedChangeListener(this);
        mLogSwitch.setOnCheckedChangeListener(this);



       // mSendButton.setOnClickListener(v-> {
       //     sendDataToBlueTooth(mSendEditText.getText().toString());
       // });
        mUpdateButton.setOnClickListener(v-> {
            startTransmission();
        });

        mGoAppButton.setOnClickListener(v-> {
            sendDataToBlueTooth(Cmd.GO_APP);
        });

        mGoDownLoadButton.setOnClickListener(v-> {
            sendDataToBlueTooth(Cmd.GO_DOWNLOAD);
        });

        mRebootChipButton.setOnClickListener(v-> {
            sendDataToBlueTooth(Cmd.REBOOT);
        });

        mStatusTextView.setText("蓝牙连接中。。。");
        mBtReceiver = new BluetoothListenerReceiver();
        registerReceiver(mBtReceiver, makeFilter());
        BleManager.getInstance().init(getApplication());
        if(isLocationEnable(this)) {
            requestPermission();
        } else {
            setLocationService();
        }

    }

    private IntentFilter makeFilter() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        return filter;
    }

    public static String bytesToHexFun(byte[] bytes) {
        StringBuilder buf = new StringBuilder(bytes.length * 2);
        for(byte b : bytes) { // 使用String的format方法进行转换
            buf.append(String.format("%02x", new Integer(b & 0xff)));
        }
        return buf.toString();
    }

    private void startTransmission(){
        //String md5 = MD5Util.MD5(mCurrentFilePath);
        mYModem = new YModem.Builder()
                .with(this)
                .filePath("assets://HAL_AutoTransmission.bin")
                .fileName("HAL_AutoTransmission.bin")
                .checkMd5("")
                .callback(new YModemListener() {
                    @Override
                    public void onDataReady(byte[] data) {
                        Log.i("AutoTrans", "onDataReady " + bytesToHexFun(data));
                        mStartUpdated = true;
                        sendDataToBlueTooth(data);
                    }

                    @Override
                    public void onProgress(int currentSent, int total) {
                        float currentPt = (float)currentSent/total;
                        int a = (int)(currentPt*100);
                        Log.i("AutoTrans", "onProgress " + a);
                        mProcessTextView.setText("升级进度："+a+"%");
                        /*
                        mUpgradeBar.setProgress(currentSent);   // Main Progress
                        mUpgradeBar.setMax(total); // Maximum Progress
                        if(a<=100){
                            mUpgradeBar.setProgressText(""+a+"%");
                        }else{
                            mUpgradeBar.setProgressText("100%");
                        }
                         */

                    }

                    @Override
                    public void onSuccess() {
                        mStartUpdated = false;
                        mFinishDownLoadTime = SystemClock.uptimeMillis();
                        long downloadTime = (mFinishDownLoadTime - mStartDownLoadTime) / 1000;
                        Toast.makeText(MainActivity.this,"固件升级完成",Toast.LENGTH_LONG).show();
                        mProcessTextView.setText("固件升级完成,耗时：" + downloadTime + "秒");
                        //finish();
                    }

                    @Override
                    public void onFailed(String reason) {
                        mStartUpdated = false;
                        Toast.makeText(MainActivity.this,reason,Toast.LENGTH_LONG).show();
                    }
                }).build();
        mYModem.start();
        mStartDownLoadTime = SystemClock.uptimeMillis();
    }

    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean check) {
        switch (compoundButton.getId()) {
            case R.id.sw1:
                if (check) {
                    try {
                        sendDataToBlueTooth(Cmd.SW1_ON);
                        Thread.sleep(30);
                        sendDataToBlueTooth(Cmd.SW2_ON);
                        Thread.sleep(30);
                        sendDataToBlueTooth(Cmd.SW3_ON);
                        Thread.sleep(30);
                        sendDataToBlueTooth(Cmd.SW4_ON);
                        Thread.sleep(30);
                        sendDataToBlueTooth(Cmd.SW5_ON);
                        Thread.sleep(30);
                        sendDataToBlueTooth(Cmd.SW6_ON);
                        Thread.sleep(30);
                        sendDataToBlueTooth(Cmd.SW7_ON);

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    sendDataToBlueTooth(Cmd.SW1_OFF);
                }
                break;
            case R.id.sw2:
                if (check) {
                    sendDataToBlueTooth(Cmd.SW2_ON);
                } else {
                    sendDataToBlueTooth(Cmd.SW2_OFF);
                }
                break;
            case R.id.sw3:
                if (check) {
                    sendDataToBlueTooth(Cmd.SW3_ON);
                } else {
                    sendDataToBlueTooth(Cmd.SW3_OFF);
                }
                break;
            case R.id.sw4:
                if (check) {
                    sendDataToBlueTooth(Cmd.SW4_ON);
                } else {
                    sendDataToBlueTooth(Cmd.SW4_OFF);
                }
                break;
            case R.id.sw5:
                if (check) {
                    sendDataToBlueTooth(Cmd.SW5_ON);
                } else {
                    sendDataToBlueTooth(Cmd.SW5_OFF);
                }
                break;
            case R.id.sw6:
                if (check) {
                    sendDataToBlueTooth(Cmd.SW6_ON);
                } else {
                    sendDataToBlueTooth(Cmd.SW6_OFF);
                }
                break;
            case R.id.sw7:
                if (check) {
                    sendDataToBlueTooth(Cmd.SW7_ON);
                } else {
                    sendDataToBlueTooth(Cmd.SW7_OFF);
                }
                break;
            case R.id.log_switch:
                mLogOpen = check;
                break;
        }
    }

    /**
     * 蓝牙状态监听器
     */
    public class BluetoothListenerReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            switch (intent.getAction()) {
                case BluetoothAdapter.ACTION_STATE_CHANGED:
                    int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
                    switch (blueState) {
                        case BluetoothAdapter.STATE_TURNING_ON:

                            break;
                        case BluetoothAdapter.STATE_ON:
                            scanAndConnectBlueTooth();
                            break;
                        case BluetoothAdapter.STATE_TURNING_OFF:

                            break;
                        case BluetoothAdapter.STATE_OFF:

                            break;
                    }
                    break;
            }

        }
    }


    private void scanAndConnectBlueTooth() {
        BleManager.getInstance()
                .enableLog(true)
                .setReConnectCount(1, 5000)
                .setSplitWriteNum(20)
                .setConnectOverTime(10000)
                .setOperateTimeout(5000);

        BleManager.getInstance().scan(new BleScanCallback() {
            @Override
            public void onScanStarted(boolean success) {

            }

            @Override
            public void onScanning(BleDevice bleDevice) {
                Log.i("AutoTrans", "onScanning " + bleDevice.getMac() + " " +  bleDevice.getName());
            }

            @Override
            public void onScanFinished(List<BleDevice> scanResultList) {
                for (BleDevice bleDevice : scanResultList) {
                    if (bleDevice.getName() != null && bleDevice.getName().equals("JDY-18")) {
                        connectBlueTooth(bleDevice);
                        break;
                    }
                }
            }
        });
    }

    private void sendDataToBlueTooth(String data) {
        BleManager.getInstance().write(mBluetoothDevice, mBluetoothGattService.getUuid().toString(), mBluetoothGattCharacteristic.getUuid().toString(), data.getBytes(),true,true, 500 ,new BleWriteCallback(){

            @Override
            public void onWriteSuccess(int current, int total, byte[] justWrite) {
                try {
                    Log.i("AutoTrans", "onWriteSuccess22 " + new String(justWrite, "utf-8"));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onWriteFailure(BleException exception) {

            }
        });
    }

    private void sendDataToBlueTooth(byte[] data) {
        BleManager.getInstance().write(mBluetoothDevice, mBluetoothGattService.getUuid().toString(), mBluetoothGattCharacteristic.getUuid().toString(), data , true,true, 25 ,new BleWriteCallback(){

            @Override
            public void onWriteSuccess(int current, int total, byte[] justWrite) {
                try {
                    Log.i("AutoTrans", "onWriteSuccess33 " + new String(justWrite, "utf-8"));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onWriteFailure(BleException exception) {

            }
        });
    }

    private void onBlueToothDataReceive(String data) {
           if (data.startsWith("STAT=")) {
               String[] dataArr = data.split("=");
               if (dataArr.length == 2) {
                   mBootStatusTextView.setText(dataArr[1]);
               }
           }

            if (data.startsWith("blc1=")) {
                String[] dataArr = data.split("=");
                if (dataArr.length >= 2) {
                    mBalance1TextView.setText(dataArr[1]);
                }
            } else if (data.startsWith("blc2=")) {
                String[] dataArr = data.split("=");
                if (dataArr.length >= 2) {
                    mBalance2TextView.setText(dataArr[1]);
                }
            }
    }


    private void connectBlueTooth(BleDevice bleDevice) {
        BleManager.getInstance().connect(bleDevice, new BleGattCallback() {
            @Override
            public void onStartConnect() {

            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {

            }
            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                mStatusTextView.setText("蓝牙已连接到：" + bleDevice.getName());
                mStatusTextView.setTextColor(Color.BLUE);
                List<BluetoothGattService> bluetoothGattServiceList = gatt.getServices();
                for(BluetoothGattService bluetoothGattService : bluetoothGattServiceList) {
                    List<BluetoothGattCharacteristic> bluetoothGattCharacteristicList = bluetoothGattService.getCharacteristics();
                    for (BluetoothGattCharacteristic bluetoothGattCharacteristic : bluetoothGattCharacteristicList) {
                        if (bluetoothGattCharacteristic.getUuid().toString().equals(HEART_RATE_MEASUREMENT)) {
                            Log.i("AutoTrans", "start notify service" + bluetoothGattService.getUuid().toString() + " chara " +  bluetoothGattCharacteristic.getUuid().toString());
                            mBluetoothGattCharacteristic = bluetoothGattCharacteristic;
                            mBluetoothDevice = bleDevice;
                            mBluetoothGattService =bluetoothGattService;
                            BleManager.getInstance().notify(bleDevice, bluetoothGattService.getUuid().toString(), bluetoothGattCharacteristic.getUuid().toString(), new BleNotifyCallback() {
                                @Override
                                public void onNotifySuccess() {

                                }

                                @Override
                                public void onNotifyFailure(BleException exception) {

                                }

                                @Override
                                public void onCharacteristicChanged(byte[] data) {
                                    try {
                                        if (mStartUpdated) {
                                            mYModem.onReceiveData(data);
                                        }
                                        if (!mLogOpen) return;
                                        Log.i("AutoTrans", "data = " + new String(data, 0, data.length, "GB2312"));
                                        if (mMsgStringBuilder.toString().length() > 3000) {
                                            mMsgStringBuilder = new StringBuilder();
                                        }
                                        mMsgStringBuilder.append("收到:");
                                        mMsgStringBuilder.append(new String(data, 0, data.length, "GB2312"));
                                        mMsgTextView.setText(mMsgStringBuilder.toString());
                                        mMsgScrollView.scrollTo(0, mMsgTextView.getMeasuredHeight());

                                        //没有处于升级过程,以换行号作为有效数据的结尾
                                        if (!mStartUpdated) {
                                            mAvailableStringBuilder.append(new String(data, 0, data.length, "GB2312"));
                                            if (new String(data, 0, data.length, "GB2312").endsWith("\n")) {
                                                //mMsgStringBuilder.append("有效数据:" + mAvailableStringBuilder.toString());
                                               // mMsgTextView.setText(mMsgStringBuilder.toString());
                                               // mMsgScrollView.scrollTo(0, mMsgTextView.getMeasuredHeight());
                                                onBlueToothDataReceive(mAvailableStringBuilder.toString().substring(0, mAvailableStringBuilder.length() - 1));
                                                mAvailableStringBuilder = new StringBuilder();
                                            }
                                        }
                                    } catch (UnsupportedEncodingException e) {
                                        e.printStackTrace();
                                    }
                                }
                            });
                        }
                    }
                }
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {
                mStatusTextView.setText("蓝牙已断开！！");
                mStatusTextView.setTextColor(Color.RED);
            }
        });
    }

    private static final int REQUEST_CODE_LOCATION_SETTINGS = 100;
    public  boolean isLocationEnable(Context context) {
        LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        boolean networkProvider = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        boolean gpsProvider = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        if (networkProvider || gpsProvider) return true;
        return false;
    }

    private void setLocationService() {
        Intent locationIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        this.startActivityForResult(locationIntent, REQUEST_CODE_LOCATION_SETTINGS);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_CODE_LOCATION_SETTINGS) {
            if (isLocationEnable(this)) {
                requestPermission();
            } else {
                finish();
            }
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

    private void requestPermission() {
        // Here, thisActivity is the current activity
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            // Should we show an explanation?
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        1);
        } else {
            if (BleManager.getInstance().isBlueEnable()) {
                Log.i("AutoTrans", "scanAndConnectBlueTooth");
                scanAndConnectBlueTooth();
            } else {
                Log.i("AutoTrans", "enableBluetooth");
                BleManager.getInstance().enableBluetooth();
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // permission was granted, yay! Do the
            // contacts-related task you need to do.
            if (BleManager.getInstance().isBlueEnable()) {
                scanAndConnectBlueTooth();
            } else {
                BleManager.getInstance().enableBluetooth();
            }
        }  else {
            finish();
        }
    }

    private int mCalWeight;
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.balance1_zero_bt:
                sendDataToBlueTooth(Cmd.BALANCE1_ZERO);
                break;
            case R.id.balance1_cal_bt:
                String cal1WeightStr = mCal1EditText.getText().toString();
                if (cal1WeightStr.isEmpty()) {
                    Toast.makeText(this, "校准值不能为空", Toast.LENGTH_LONG).show();
                } else {
                    int cal1Weight = Integer.parseInt(cal1WeightStr);
                    sendCalCmd(1, cal1Weight);
                }
                break;
            case R.id.balance2_zero_bt:
                sendDataToBlueTooth(Cmd.BALANCE2_ZERO);
                break;
            case R.id.balance2_cal_bt:
                String cal2WeightStr = mCal2EditText.getText().toString();
                if (cal2WeightStr.isEmpty()) {
                    Toast.makeText(this, "校准值不能为空", Toast.LENGTH_LONG).show();
                } else {
                    int cal2Weight = Integer.parseInt(cal2WeightStr);
                    sendCalCmd(2, cal2Weight);
                }
                break;
        }
    }

    private void sendCalCmd(int calNum, int calWeight) {
        byte[] cmd = new byte[6];
        if (calNum == 1) {
            cmd[0] = Cmd.BALANCE1_CAL_START_BYTE;
        } else if (calNum == 2) {
            cmd[0] = Cmd.BALANCE2_CAL_START_BYTE;
        }


        byte[] res = parseIntegerToByteArray(calWeight);
        for (int i = 0; i < res.length; i++) {
            cmd[i+1] = res[i];
        }
        cmd[5] = Cmd.END_BYTE;
        sendDataToBlueTooth(cmd);
    }

    private byte[] parseIntegerToByteArray(int num) {
        byte[] result = new byte[4];
        result[0] = (byte)num;
        result[1] = (byte)(num >> 8);
        result[2] = (byte)(num >> 16);
        result[3] = (byte)(num >> 24);
        return result;
    }

}
